using UnityEngine;
using System.Collections;

public class SlabResize : MonoBehaviour
{

	public enum SlabFace
	{
		TOP,
		SIDE
	}

	private RaycastHit hit = new RaycastHit ();
	private float mouseDownReferenceX = 0, mouseDownReferenceY = 0;
	private Vector3 localSlabSideNormalVector;
	private bool slabHit;

	// Use this for initialization
	void Start ()
	{
		localSlabSideNormalVector = Vector3.zero;
		slabHit = false;
	}

	// Update is called once per frame
	void Update ()
	{
		manageResizeWithMouseEvents ();
	}

	void manageResizeWithMouseEvents ()
	{
		
		// Moment unique lors de l appui sur clique droit
		if (Input.GetMouseButtonDown (1)) {
			mouseDownReferenceX = Input.mousePosition.x;
			mouseDownReferenceY = Input.mousePosition.y;
			
			Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);
			
			if (Physics.Raycast (ray.origin, ray.direction, out hit, Mathf.Infinity)) {
				
				if (hit.collider.gameObject == this.gameObject) {
					// Slab hit is slab where this script is attached
					// Convert hit normal to local space of the slab to know which side has been hit. And Store It
					slabHit = true;
					localSlabSideNormalVector = transform.InverseTransformDirection (hit.normal);
				}
			}
		}
		
		// Toujours appelé lorsque clique droit est préssé:
		if (Input.GetMouseButton (1) && slabHit) {
			
			float deltaMouseDownReferenceX = Input.mousePosition.x - mouseDownReferenceX;
			float deltaMouseDownReferenceY = Input.mousePosition.y - mouseDownReferenceY;
			
			// Resize Slab on runtime
			Vector3 previousSlabScale = transform.localScale; // Store previous size
			
			Vector3 newSlabScaleDelta = Vector3.zero; // Init new amout of new size
			
			float wayInOrderToRescaleSlab = 1;
			
			switch (getMouseMovement (localSlabSideNormalVector)) {
			
				case SlabFace.TOP:

					newSlabScaleDelta = localSlabSideNormalVector * deltaMouseDownReferenceY;
					break;
					
				case SlabFace.SIDE:
	
					Vector3 worldObjectFaceNormal = hit.normal;
					if(isObjectFaceFrontToCam (Camera.main, worldObjectFaceNormal)) { // Face front to cam
						newSlabScaleDelta = localSlabSideNormalVector * deltaMouseDownReferenceY;
					} else { // Face side to cam

						if(localSlabSideNormalVector.z != 0) { // Z face
							Vector3 slabForwardVector =  transform.TransformDirection(Vector3.forward);
							if (Mathf.Sign(slabForwardVector.x) == -1) {
								wayInOrderToRescaleSlab = -1;
							}
						}
						
						if(localSlabSideNormalVector.x != 0) { // X face
							Vector3 slabForwardVector =  transform.TransformDirection(Vector3.forward);
							if (Mathf.Sign(slabForwardVector.z) == -1) {
								wayInOrderToRescaleSlab = -1;
							}
						}
						
						newSlabScaleDelta = localSlabSideNormalVector * deltaMouseDownReferenceX * wayInOrderToRescaleSlab;
						
//						Debug.Log(localSlabSideNormalVector);
					}
					break;
			}
			
			// Apply size change
			newSlabScaleDelta = newSlabScaleDelta * 0.1f * Time.deltaTime;
			Vector3 expectedNewSize = previousSlabScale + newSlabScaleDelta;
			
			if (isCompliantNewSize (expectedNewSize)) {
				transform.localScale = expectedNewSize;
				
				// Readjust position
				Vector3 previousPos  = transform.position;
				previousPos.y = previousPos.y + newSlabScaleDelta.y / 2.0f;
				transform.position = previousPos;
			}
		
		}
		
		if (Input.GetMouseButtonUp (1)) {
			slabHit = false;
		}
		
	}

	public bool isObjectFaceFrontToCam (Camera camera, Vector3 worldObjectFaceNormal)
	{
		float dot = Vector3.Dot (hit.normal, Camera.main.transform.forward);
		return (Mathf.Abs (dot) > Mathf.Cos (Mathf.Deg2Rad * 45)) ? true : false;
	}

	public SlabFace getMouseMovement (Vector3 sizeDirection)
	{
		float dotProduct = Vector3.Dot (Vector3.up, sizeDirection);
		return (dotProduct == 1) ? SlabFace.TOP : SlabFace.SIDE;
	}

	public bool isCompliantNewSize (Vector3 newSize)
	{
		return (newSize.x < 0.5f || newSize.y < 0.1f || newSize.z < 0.5f) ? false : true;
	}

	void OnDrawGizmos ()
	{
		Debug.DrawRay (hit.point, hit.normal, Color.magenta);
		
	}
	
}